home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / powerrom_cpu / powerrom_cpu.cpp < prev   
Encoding:
C/C++ Source or Header  |  2001-02-10  |  39.4 KB  |  1,366 lines

  1. /*
  2.  *  powerrom_cpu.cpp - Using the 680x0 emulator in PowerMac ROMs for Basilisk II
  3.  *
  4.  *  Basilisk II (C) 1997-2001 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include <unistd.h>
  22. #include <signal.h>
  23. #include <stdlib.h>
  24.  
  25. #include <AppKit.h>
  26. #include <KernelKit.h>
  27. #include <StorageKit.h>
  28.  
  29. #include "sysdeps.h"
  30. #include "cpu_emulation.h"
  31. #include "main.h"
  32. #include "emul_op.h"
  33. #include "prefs.h"
  34. #include "user_strings.h"
  35.  
  36. #include "sheep_driver.h"
  37.  
  38. #define DEBUG 0
  39. #include "debug.h"
  40.  
  41. // Save FP regs in Execute68k()?
  42. #define SAVE_FP_EXEC_68K 0
  43.  
  44.  
  45. // Constants
  46. const char ROM_FILE_NAME[] = "PowerROM";
  47. const char KERNEL_AREA_NAME[] = "Macintosh Kernel Data";
  48. const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache";
  49.  
  50. const uint32 ROM_BASE = 0x40800000;            // Base address of ROM
  51. const uint32 ROM_SIZE = 0x00400000;            // Size of ROM file
  52. const uint32 ROM_AREA_SIZE = 0x00500000;    // Size of ROM area
  53.  
  54. const uint32 DR_CACHE_BASE = 0x69000000;    // Address of DR cache
  55. const uint32 DR_CACHE_SIZE = 0x80000;        // Size of DR Cache
  56.  
  57. const uint32 SIG_STACK_SIZE = 8192;            // Size of signal stack
  58.  
  59. // PowerPC opcodes
  60. const uint32 POWERPC_NOP = 0x60000000;
  61. const uint32 POWERPC_ILLEGAL = 0x00000000;
  62. const uint32 POWERPC_BLR = 0x4e800020;
  63. const uint32 POWERPC_BCTR = 0x4e800420;
  64.  
  65. // Extra Low Memory Globals
  66. #define MODE_68K 0        // 68k emulator active
  67. #define MODE_EMUL_OP 1    // Within EMUL_OP routine
  68.  
  69. #define XLM_RESET_STACK 0x2800            // Reset stack pointer
  70. #define XLM_KERNEL_DATA 0x2804            // Pointer to Kernel Data
  71. #define XLM_TOC 0x2808                    // TOC pointer of emulator
  72. #define XLM_RUN_MODE 0x2810                // Current run mode, see enum above
  73. #define XLM_68K_R25 0x2814                // Contents of the 68k emulator's r25 (which contains the interrupt level), saved upon entering EMUL_OP mode, used by Execute68k() and the USR1 signal handler
  74. #define XLM_IRQ_NEST 0x2818                // Interrupt disable nesting counter (>0: disabled)
  75. #define XLM_PVR 0x281c                    // Theoretical PVR
  76. #define XLM_EMUL_RETURN_PROC 0x2824        // Pointer to EMUL_RETURN routine
  77. #define XLM_EXEC_RETURN_PROC 0x2828        // Pointer to EXEC_RETURN routine
  78. #define XLM_EMUL_OP_PROC 0x282c            // Pointer to EMUL_OP routine
  79. #define XLM_EMUL_RETURN_STACK 0x2830    // Stack pointer for EMUL_RETURN
  80.  
  81.  
  82. // RAM and ROM pointers
  83. uint32 RAMBaseMac;            // RAM base (Mac address space)
  84. uint8 *RAMBaseHost;            // RAM base (host address space)
  85. uint32 RAMSize;                // Size of RAM
  86. uint32 ROMBaseMac;            // ROM base (Mac address space)
  87. uint8 *ROMBaseHost;            // ROM base (host address space)
  88. uint32 ROMSize;                // Size of ROM
  89.  
  90.  
  91. // Emulator Data
  92. struct EmulatorData {
  93.     uint32    v[0x400];    
  94. };
  95.  
  96.  
  97. // Kernel Data
  98. struct KernelData {
  99.     uint32    v[0x400];
  100.     EmulatorData ed;
  101. };
  102.  
  103.  
  104. // Exceptions
  105. class file_open_error {};
  106. class file_read_error {};
  107. class rom_size_error {};
  108.  
  109.  
  110. // Global variables
  111. static void *TOC;                        // TOC pointer
  112. static uint32 PVR;                        // Theoretical PVR
  113. static int64 CPUClockSpeed;                // Processor clock speed (Hz)
  114. static int64 BusClockSpeed;                // Bus clock speed (Hz)
  115. static system_info SysInfo;                // System information
  116.  
  117. static area_id kernel_area = -1;        // Kernel Data area ID
  118. static KernelData *kernel_data = NULL;    // Pointer to Kernel Data
  119. static uint32 KernelDataAddr;            // Address of Kernel Data
  120. static EmulatorData *emulator_data = NULL;
  121. static area_id dr_cache_area;            // DR Cache area ID
  122. static uint32 DRCacheAddr;                // Address of DR Cache
  123.  
  124. static struct sigaction sigusr1_action;    // Interrupt signal (of emulator thread)
  125. static bool ReadyForSignals = false;    // Flag: emul_thread ready to receive signals
  126.  
  127.  
  128. // Prototypes
  129. static void sigusr1_handler(int sig, void *arg, vregs *r);
  130.  
  131. // From main_beos.cpp
  132. extern int sheep_fd;                    // fd of sheep driver
  133. extern thread_id emul_thread;            // Emulator thread
  134.  
  135.  
  136. /*
  137.  *  Load ROM file (upper 3MB)
  138.  *
  139.  *  file_open_error: Cannot open ROM file (nor use built-in ROM)
  140.  *  file_read_error: Cannot read ROM file
  141.  */
  142.  
  143. // Decode LZSS data
  144. static void decode_lzss(const uint8 *src, uint8 *dest, int size)
  145. {
  146.     char dict[0x1000];
  147.     int run_mask = 0, dict_idx = 0xfee;
  148.     for (;;) {
  149.         if (run_mask < 0x100) {
  150.             // Start new run
  151.             if (--size < 0)
  152.                 break;
  153.             run_mask = *src++ | 0xff00;
  154.         }
  155.         bool bit = run_mask & 1;
  156.         run_mask >>= 1;
  157.         if (bit) {
  158.             // Verbatim copy
  159.             if (--size < 0)
  160.                 break;
  161.             int c = *src++;
  162.             dict[dict_idx++] = c;
  163.             *dest++ = c;
  164.             dict_idx &= 0xfff;
  165.         } else {
  166.             // Copy from dictionary
  167.             if (--size < 0)
  168.                 break;
  169.             int idx = *src++;
  170.             if (--size < 0)
  171.                 break;
  172.             int cnt = *src++;
  173.             idx |= (cnt << 4) & 0xf00;
  174.             cnt = (cnt & 0x0f) + 3;
  175.             while (cnt--) {
  176.                 char c = dict[idx++];
  177.                 dict[dict_idx++] = c;
  178.                 *dest++ = c;
  179.                 idx &= 0xfff;
  180.                 dict_idx &= 0xfff;
  181.             }
  182.         }
  183.     }
  184. }
  185.  
  186. static void load_rom(void)
  187. {
  188.     // Get rom file path from preferences
  189.     const char *rom_path = PrefsFindString("powerrom");
  190.  
  191.     // Try to open ROM file
  192.     BFile file(rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY);
  193.     if (file.InitCheck() != B_NO_ERROR) {
  194.  
  195.         // Failed, then ask sheep driver for ROM
  196.         uint8 *rom = new uint8[ROM_SIZE];    // Reading directly into the area doesn't work
  197.         ssize_t actual = read(sheep_fd, (void *)rom, ROM_SIZE);
  198.         if (actual == ROM_SIZE) {
  199.             // Copy upper 3MB
  200.             memcpy((void *)(ROM_BASE + 0x100000), rom + 0x100000, ROM_SIZE - 0x100000);
  201.             delete[] rom;
  202.             return;
  203.         } else
  204.             throw file_open_error();
  205.     }
  206.  
  207.     printf(GetString(STR_READING_ROM_FILE));
  208.  
  209.     // Get file size
  210.     off_t rom_size = 0;
  211.     file.GetSize(&rom_size);
  212.  
  213.     uint8 *rom = new uint8[ROM_SIZE];    // Reading directly into the area doesn't work
  214.     ssize_t actual = file.Read((void *)rom, ROM_SIZE);
  215.     if (actual == ROM_SIZE) {
  216.         // Plain ROM image, copy upper 3MB
  217.         memcpy((void *)(ROM_BASE + 0x100000), rom + 0x100000, ROM_SIZE - 0x100000);
  218.         delete[] rom;
  219.     } else {
  220.         if (strncmp((char *)rom, "<CHRP-BOOT>", 11) == 0) {
  221.             // CHRP compressed ROM image
  222.             D(bug("CHRP ROM image\n"));
  223.             uint32 lzss_offset, lzss_size;
  224.  
  225.             char *s = strstr((char *)rom, "constant lzss-offset"); 
  226.             if (s == NULL)
  227.                 throw rom_size_error();
  228.             s -= 7;
  229.             if (sscanf(s, "%06lx", &lzss_offset) != 1)
  230.                 throw rom_size_error();
  231.             s = strstr((char *)rom, "constant lzss-size"); 
  232.             if (s == NULL)
  233.                 throw rom_size_error();
  234.             s -= 7;
  235.             if (sscanf(s, "%06lx", &lzss_size) != 1)
  236.                 throw rom_size_error();
  237.             D(bug("Offset of compressed data: %08lx\n", lzss_offset));
  238.             D(bug("Size of compressed data: %08lx\n", lzss_size));
  239.  
  240.             D(bug("Uncompressing ROM...\n"));
  241.             uint8 *decoded = new uint8[ROM_SIZE];
  242.             decode_lzss(rom + lzss_offset, decoded, lzss_size);
  243.             memcpy((void *)(ROM_BASE + 0x100000), decoded + 0x100000, ROM_SIZE - 0x100000);
  244.             delete[] decoded;
  245.             delete[] rom;
  246.         } else if (rom_size != 4*1024*1024)
  247.             throw rom_size_error();
  248.         else
  249.             throw file_read_error();
  250.     }
  251. }
  252.  
  253.  
  254. /*
  255.  *  Patch PowerMac ROM
  256.  */
  257.  
  258. // ROM type
  259. enum {
  260.     ROMTYPE_TNT,
  261.     ROMTYPE_ALCHEMY,
  262.     ROMTYPE_ZANZIBAR,
  263.     ROMTYPE_GAZELLE,
  264.     ROMTYPE_NEWWORLD
  265. };
  266. static int ROMType;
  267.  
  268. // Nanokernel boot routine patches
  269. static bool patch_nanokernel_boot(void)
  270. {
  271.     uint32 *lp;
  272.     int i;
  273.  
  274.     // Patch ConfigInfo
  275.     lp = (uint32 *)(ROM_BASE + 0x30d000);
  276.     lp[0x9c >> 2] = KernelDataAddr;            // LA_InfoRecord
  277.     lp[0xa0 >> 2] = KernelDataAddr;            // LA_KernelData
  278.     lp[0xa4 >> 2] = KernelDataAddr + 0x1000;// LA_EmulatorData
  279.     lp[0xa8 >> 2] = ROM_BASE + 0x480000;    // LA_DispatchTable
  280.     lp[0xac >> 2] = ROM_BASE + 0x460000;    // LA_EmulatorCode
  281.     lp[0x360 >> 2] = 0;                        // Physical RAM base (? on NewWorld ROM, this contains -1)
  282.     lp[0xfd8 >> 2] = ROM_BASE + 0x2a;        // 68k reset vector
  283.  
  284.     // Skip SR/BAT/SDR init
  285.     if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_NEWWORLD) {
  286.         lp = (uint32 *)(ROM_BASE + 0x310000);
  287.         *lp++ = POWERPC_NOP;
  288.         *lp = 0x38000000;
  289.     }
  290.     static const uint32 sr_init_loc[] = {0x3101b0, 0x3101b0, 0x3101b0, 0x3101ec, 0x310200};
  291.     lp = (uint32 *)(ROM_BASE + 0x310008);
  292.     *lp = 0x48000000 | (sr_init_loc[ROMType] - 8) & 0xffff;    // b        ROM_BASE+0x3101b0
  293.     lp = (uint32 *)(ROM_BASE + sr_init_loc[ROMType]);
  294.     *lp++ = 0x80200000 + XLM_KERNEL_DATA;    // lwz    r1,(pointer to Kernel Data)
  295.     *lp++ = 0x3da0dead;                        // lis    r13,0xdead    (start of kernel memory)
  296.     *lp++ = 0x3dc00010;                        // lis    r14,0x0010    (size of page table)
  297.     *lp = 0x3de00010;                        // lis    r15,0x0010    (size of kernel memory)
  298.  
  299.     // Don't read PVR
  300.     static const uint32 pvr_loc[] = {0x3103b0, 0x3103b4, 0x3103b4, 0x310400, 0x310438};
  301.     lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]);
  302.     *lp = 0x81800000 + XLM_PVR;    // lwz    r12,(theoretical PVR)
  303.  
  304.     // Set CPU specific data (even if ROM doesn't have support for that CPU)
  305.     lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]);
  306.     if (ntohl(lp[6]) != 0x2c0c0001)
  307.         return false;
  308.     uint32 ofs = lp[7] & 0xffff;
  309.     lp[8] = (lp[8] & 0xffff) | 0x48000000;    // beq -> b
  310.     uint32 loc = (lp[8] & 0xffff) + (uint32)(lp+8) - ROM_BASE;
  311.     lp = (uint32 *)(ROM_BASE + ofs + 0x310000);
  312.     switch (PVR >> 16) {
  313.         case 1:        // 601
  314.             lp[0] = 0x1000;        // Page size
  315.             lp[1] = 0x8000;        // Data cache size
  316.             lp[2] = 0x8000;        // Inst cache size
  317.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  318.             lp[4] = 0x00010040;    // Unified caches/Inst cache line size
  319.             lp[5] = 0x00400020;    // Data cache line size/Data cache block size touch
  320.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  321.             lp[7] = 0x00080008;    // Inst cache assoc/Data cache assoc
  322.             lp[8] = 0x01000002;    // TLB total size/TLB assoc
  323.             break;
  324.         case 3:        // 603
  325.             lp[0] = 0x1000;        // Page size
  326.             lp[1] = 0x2000;        // Data cache size
  327.             lp[2] = 0x2000;        // Inst cache size
  328.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  329.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  330.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  331.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  332.             lp[7] = 0x00020002;    // Inst cache assoc/Data cache assoc
  333.             lp[8] = 0x00400002;    // TLB total size/TLB assoc
  334.             break;
  335.         case 4:        // 604
  336.             lp[0] = 0x1000;        // Page size
  337.             lp[1] = 0x4000;        // Data cache size
  338.             lp[2] = 0x4000;        // Inst cache size
  339.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  340.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  341.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  342.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  343.             lp[7] = 0x00040004;    // Inst cache assoc/Data cache assoc
  344.             lp[8] = 0x00800002;    // TLB total size/TLB assoc
  345.             break;
  346. //        case 5:        // 740?
  347.         case 6:        // 603e
  348.         case 7:        // 603ev
  349.             lp[0] = 0x1000;        // Page size
  350.             lp[1] = 0x4000;        // Data cache size
  351.             lp[2] = 0x4000;        // Inst cache size
  352.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  353.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  354.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  355.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  356.             lp[7] = 0x00040004;    // Inst cache assoc/Data cache assoc
  357.             lp[8] = 0x00400002;    // TLB total size/TLB assoc
  358.             break;
  359.         case 8:        // 750
  360.             lp[0] = 0x1000;        // Page size
  361.             lp[1] = 0x8000;        // Data cache size
  362.             lp[2] = 0x8000;        // Inst cache size
  363.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  364.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  365.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  366.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  367.             lp[7] = 0x00080008;    // Inst cache assoc/Data cache assoc
  368.             lp[8] = 0x00800002;    // TLB total size/TLB assoc
  369.             break;
  370.         case 9:        // 604e
  371.         case 10:    // 604ev5
  372.             lp[0] = 0x1000;        // Page size
  373.             lp[1] = 0x8000;        // Data cache size
  374.             lp[2] = 0x8000;        // Inst cache size
  375.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  376.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  377.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  378.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  379.             lp[7] = 0x00040004;    // Inst cache assoc/Data cache assoc
  380.             lp[8] = 0x00800002;    // TLB total size/TLB assoc
  381.             break;
  382. //        case 11:    // X704?
  383.         case 12:    // ???
  384.             lp[0] = 0x1000;        // Page size
  385.             lp[1] = 0x8000;        // Data cache size
  386.             lp[2] = 0x8000;        // Inst cache size
  387.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  388.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  389.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  390.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  391.             lp[7] = 0x00080008;    // Inst cache assoc/Data cache assoc
  392.             lp[8] = 0x00800002;    // TLB total size/TLB assoc
  393.             break;
  394.         case 13:    // ???
  395.             lp[0] = 0x1000;        // Page size
  396.             lp[1] = 0x8000;        // Data cache size
  397.             lp[2] = 0x8000;        // Inst cache size
  398.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  399.             lp[4] = 0x00000020;    // Unified caches/Inst cache line size
  400.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  401.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  402.             lp[7] = 0x00080008;    // Inst cache assoc/Data cache assoc
  403.             lp[8] = 0x01000004;    // TLB total size/TLB assoc
  404.             break;
  405. //        case 50:    // 821
  406. //        case 80:    // 860
  407.         case 96:    // ???
  408.             lp[0] = 0x1000;        // Page size
  409.             lp[1] = 0x8000;        // Data cache size
  410.             lp[2] = 0x8000;        // Inst cache size
  411.             lp[3] = 0x00200020;    // Coherency block size/Reservation granule size
  412.             lp[4] = 0x00010020;    // Unified caches/Inst cache line size
  413.             lp[5] = 0x00200020;    // Data cache line size/Data cache block size touch
  414.             lp[6] = 0x00200020;    // Inst cache block size/Data cache block size
  415.             lp[7] = 0x00080008;    // Inst cache assoc/Data cache assoc
  416.             lp[8] = 0x00800004;    // TLB total size/TLB assoc
  417.             break;
  418.         default:
  419.             printf("WARNING: Unknown CPU type\n");
  420.             break;
  421.     }
  422.  
  423.     // Don't set SPRG3, don't test MQ
  424.     lp = (uint32 *)(ROM_BASE + loc + 0x20);
  425.     *lp++ = POWERPC_NOP;
  426.     lp++;
  427.     *lp++ = POWERPC_NOP;
  428.     lp++;
  429.     *lp = POWERPC_NOP;
  430.  
  431.     // Don't read MSR
  432.     lp = (uint32 *)(ROM_BASE + loc + 0x40);
  433.     *lp = 0x39c00000;        // li    r14,0
  434.  
  435.     // Don't write to DEC
  436.     lp = (uint32 *)(ROM_BASE + loc + 0x70);
  437.     *lp++ = POWERPC_NOP;
  438.     loc = (lp[0] & 0xffff) + (uint32)lp - ROM_BASE;
  439.  
  440.     // Don't set SPRG3
  441.     lp = (uint32 *)(ROM_BASE + loc + 0x2c);
  442.     *lp = POWERPC_NOP;
  443.  
  444.     // Don't read PVR
  445.     static const uint32 pvr_ofs[] = {0x138, 0x138, 0x138, 0x140, 0x148};
  446.     lp = (uint32 *)(ROM_BASE + loc + pvr_ofs[ROMType]);
  447.     *lp = 0x82e00000 + XLM_PVR;        // lwz    r23,(theoretical PVR)
  448.     lp = (uint32 *)(ROM_BASE + loc + 0x170);
  449.     if (*lp == 0x7eff42a6)        // NewWorld ROM
  450.         *lp = 0x82e00000 + XLM_PVR;    // lwz    r23,(theoretical PVR)
  451.     lp = (uint32 *)(ROM_BASE + 0x313134);
  452.     if (*lp == 0x7e5f42a6)
  453.         *lp = 0x82400000 + XLM_PVR;    // lwz    r18,(theoretical PVR)
  454.     lp = (uint32 *)(ROM_BASE + 0x3131f4);
  455.     if (*lp == 0x7e5f42a6)        // NewWorld ROM
  456.         *lp = 0x82400000 + XLM_PVR;    // lwz    r18,(theoretical PVR)
  457.  
  458.     // Don't read SDR1
  459.     static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c};
  460.     lp = (uint32 *)(ROM_BASE + loc + sdr1_ofs[ROMType]);
  461.     *lp++ = 0x3d00dead;        // lis    r8,0xdead        (pointer to page table)
  462.     *lp++ = 0x3ec0001f;        // lis    r22,0x001f    (size of page table)
  463.     *lp = POWERPC_NOP;
  464.  
  465.     // Don't clear page table
  466.     static const uint32 pgtb_ofs[] = {0x198, 0x198, 0x198, 0x1a0, 0x1c4};
  467.     lp = (uint32 *)(ROM_BASE + loc + pgtb_ofs[ROMType]);
  468.     *lp = POWERPC_NOP;
  469.  
  470.     // Don't invalidate TLB
  471.     static const uint32 tlb_ofs[] = {0x1a0, 0x1a0, 0x1a0, 0x1a8, 0x1cc};
  472.     lp = (uint32 *)(ROM_BASE + loc + tlb_ofs[ROMType]);
  473.     *lp = POWERPC_NOP;
  474.  
  475.     // Don't create RAM descriptor table
  476.     static const uint32 desc_ofs[] = {0x350, 0x350, 0x350, 0x358, 0x37c};
  477.     lp = (uint32 *)(ROM_BASE + loc + desc_ofs[ROMType]);
  478.     *lp = POWERPC_NOP;
  479.  
  480.     // Don't load SRs and BATs
  481.     static const uint32 sr_ofs[] = {0x3d8, 0x3d8, 0x3d8, 0x3e0, 0x404};
  482.     lp = (uint32 *)(ROM_BASE + loc + sr_ofs[ROMType]);
  483.     *lp = POWERPC_NOP;
  484.  
  485.     // Don't mess with SRs
  486.     static const uint32 sr2_ofs[] = {0x312118, 0x312118, 0x312118, 0x312118, 0x3121b4};
  487.     lp = (uint32 *)(ROM_BASE + sr2_ofs[ROMType]);
  488.     *lp = POWERPC_BLR;
  489.  
  490.     // Don't check performance monitor
  491.     static const uint32 pm_ofs[] = {0x313148, 0x313148, 0x313148, 0x313148, 0x313218};
  492.     lp = (uint32 *)(ROM_BASE + pm_ofs[ROMType]);
  493.     while (*lp != 0x7e58eba6) lp++;
  494.     *lp++ = POWERPC_NOP;
  495.     while (*lp != 0x7e78eaa6) lp++;
  496.     *lp++ = POWERPC_NOP;
  497.     while (*lp != 0x7e59eba6) lp++;
  498.     *lp++ = POWERPC_NOP;
  499.     while (*lp != 0x7e79eaa6) lp++;
  500.     *lp++ = POWERPC_NOP;
  501.     while (*lp != 0x7e5aeba6) lp++;
  502.     *lp++ = POWERPC_NOP;
  503.     while (*lp != 0x7e7aeaa6) lp++;
  504.     *lp++ = POWERPC_NOP;
  505.     while (*lp != 0x7e5beba6) lp++;
  506.     *lp++ = POWERPC_NOP;
  507.     while (*lp != 0x7e7beaa6) lp++;
  508.     *lp++ = POWERPC_NOP;
  509.     while (*lp != 0x7e5feba6) lp++;
  510.     *lp++ = POWERPC_NOP;
  511.     while (*lp != 0x7e7feaa6) lp++;
  512.     *lp++ = POWERPC_NOP;
  513.     while (*lp != 0x7e5ceba6) lp++;
  514.     *lp++ = POWERPC_NOP;
  515.     while (*lp != 0x7e7ceaa6) lp++;
  516.     *lp++ = POWERPC_NOP;
  517.     while (*lp != 0x7e5deba6) lp++;
  518.     *lp++ = POWERPC_NOP;
  519.     while (*lp != 0x7e7deaa6) lp++;
  520.     *lp++ = POWERPC_NOP;
  521.     while (*lp != 0x7e5eeba6) lp++;
  522.     *lp++ = POWERPC_NOP;
  523.     while (*lp != 0x7e7eeaa6) lp++;
  524.     *lp++ = POWERPC_NOP;
  525.  
  526.     // Jump to 68k emulator
  527.     static const uint32 jump68k_ofs[] = {0x40c, 0x40c, 0x40c, 0x414, 0x438};
  528.     lp = (uint32 *)(ROM_BASE + loc + jump68k_ofs[ROMType]);
  529.     *lp++ = 0x80610634;        // lwz    r3,0x0634(r1)    (pointer to Emulator Data)
  530.     *lp++ = 0x8081119c;        // lwz    r4,0x119c(r1)    (pointer to opcode table)
  531.     *lp++ = 0x80011184;        // lwz    r0,0x1184(r1)    (pointer to emulator entry)
  532.     *lp++ = 0x7c0903a6;        // mtctr    r0
  533.     *lp = POWERPC_BCTR;
  534.     return true;
  535. }
  536.  
  537. // 68k emulator patches
  538. static bool patch_68k_emul(void)
  539. {
  540.     uint32 *lp;
  541.     uint32 base;
  542.  
  543.     // Overwrite twi instructions
  544.     static const uint32 twi_loc[] = {0x36e680, 0x36e6c0, 0x36e6c0, 0x36e6c0, 0x36e740};
  545.     base = twi_loc[ROMType];
  546.     lp = (uint32 *)(ROM_BASE + base);
  547.     *lp++ = 0x48000000 + 0x36f900 - base;        // b 0x36f900 (Emulator start)
  548.     *lp++ = POWERPC_ILLEGAL;
  549.     *lp++ = 0x48000000 + 0x36fb00 - base - 8;    // b 0x36fb00 (Reset opcode)
  550.     *lp++ = POWERPC_ILLEGAL;
  551.     *lp++ = POWERPC_ILLEGAL;
  552.     *lp++ = POWERPC_ILLEGAL;
  553.     *lp++ = POWERPC_ILLEGAL;
  554.     *lp++ = POWERPC_ILLEGAL;
  555.     *lp++ = POWERPC_ILLEGAL;
  556.     *lp++ = POWERPC_ILLEGAL;
  557.     *lp++ = POWERPC_ILLEGAL;
  558.     *lp++ = POWERPC_ILLEGAL;
  559.     *lp++ = POWERPC_ILLEGAL;
  560.     *lp++ = POWERPC_ILLEGAL;
  561.     *lp++ = POWERPC_ILLEGAL;
  562.     *lp++ = POWERPC_ILLEGAL;
  563.  
  564.     // Set reset stack pointer
  565.     lp = (uint32 *)(ROM_BASE + base + 0xf0);
  566.     *lp++ = 0x80200000 + XLM_RESET_STACK;            // lwz        r1,XLM_RESET_STACK
  567.  
  568.     // Install EXEC_RETURN and EMUL_OP opcodes
  569.     lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EXEC_RETURN << 3));
  570.     *lp++ = 0x80000000 + XLM_EXEC_RETURN_PROC;        // lwz    r0,XLM_EXEC_RETURN_PROC
  571.     *lp++ = 0x4bfb6ffc;                                // b    0x36f800
  572.     for (int i=0; i<M68K_EMUL_OP_MAX-M68K_EMUL_BREAK; i++) {
  573.         *lp++ = 0x38a00000 + i + M68K_EMUL_BREAK;    // li    r5,M68K_EMUL_OP_*
  574.         *lp++ = 0x4bfb6ffc - i*8;                    // b    0x36f808
  575.     }
  576.  
  577.     // Special handling for M68K_EMUL_OP_SHUTDOWN because Basilisk II is running
  578.     // on the 68k stack and simply quitting would delete the RAM area leaving
  579.     // the stack pointer in unaccessible memory
  580.     lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_OP_SHUTDOWN << 3));
  581.     *lp++ = 0x80000000 + XLM_EMUL_RETURN_PROC;        // lwz    r0,XLM_EMUL_RETURN_PROC
  582.     *lp++ = 0x4bfb6ffc - (M68K_EMUL_OP_SHUTDOWN - M68K_EXEC_RETURN) * 8;    // b    0x36f800
  583.  
  584.     // Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP
  585.     lp = (uint32 *)(ROM_BASE + 0x36f800);
  586.     *lp++ = 0x7c0803a6;                    // mtlr    r0
  587.     *lp++ = 0x4e800020;                    // blr
  588.  
  589.     *lp++ = 0x80000000 + XLM_EMUL_OP_PROC;    // lwz    r0,XLM_EMUL_OP_PROC
  590.     *lp++ = 0x7c0803a6;                    // mtlr    r0
  591.     *lp++ = 0x4e800020;                    // blr
  592.  
  593.     // Extra routine for 68k emulator start
  594.     lp = (uint32 *)(ROM_BASE + 0x36f900);
  595.     *lp++ = 0x7c2903a6;                    // mtctr    r1
  596.     *lp++ = 0x80200000 + XLM_IRQ_NEST;    // lwz        r1,XLM_IRQ_NEST
  597.     *lp++ = 0x38210001;                    // addi        r1,r1,1
  598.     *lp++ = 0x90200000 + XLM_IRQ_NEST;    // stw        r1,XLM_IRQ_NEST
  599.     *lp++ = 0x80200000 + XLM_KERNEL_DATA;// lwz        r1,XLM_KERNEL_DATA
  600.     *lp++ = 0x90c10018;                    // stw        r6,0x18(r1)
  601.     *lp++ = 0x7cc902a6;                    // mfctr    r6
  602.     *lp++ = 0x90c10004;                    // stw        r6,$0004(r1)
  603.     *lp++ = 0x80c1065c;                    // lwz        r6,$065c(r1)
  604.     *lp++ = 0x90e6013c;                    // stw        r7,$013c(r6)
  605.     *lp++ = 0x91060144;                    // stw        r8,$0144(r6)
  606.     *lp++ = 0x9126014c;                    // stw        r9,$014c(r6)
  607.     *lp++ = 0x91460154;                    // stw        r10,$0154(r6)
  608.     *lp++ = 0x9166015c;                    // stw        r11,$015c(r6)
  609.     *lp++ = 0x91860164;                    // stw        r12,$0164(r6)
  610.     *lp++ = 0x91a6016c;                    // stw        r13,$016c(r6)
  611.     *lp++ = 0x7da00026;                    // mfcr        r13
  612.     *lp++ = 0x80e10660;                    // lwz        r7,$0660(r1)
  613.     *lp++ = 0x7d8802a6;                    // mflr        r12
  614.     *lp++ = 0x50e74001;                    // rlwimi.    r7,r7,8,$80000000
  615.     *lp++ = 0x814105f0;                    // lwz        r10,0x05f0(r1)
  616.     *lp++ = 0x7d4803a6;                    // mtlr        r10
  617.     *lp++ = 0x7d8a6378;                    // mr        r10,r12
  618.     *lp++ = 0x3d600002;                    // lis        r11,0x0002
  619.     *lp++ = 0x616bf072;                    // ori        r11,r11,0xf072 (MSR)
  620.     *lp++ = 0x50e7deb4;                    // rlwimi    r7,r7,27,$00000020
  621.     *lp++ = 0x4e800020;                    // blr
  622.  
  623.     // Extra routine for Reset opcode
  624.     lp = (uint32 *)(ROM_BASE + 0x36fc00);
  625.     *lp++ = 0x7c2903a6;                    // mtctr    r1
  626.     *lp++ = 0x80200000 + XLM_IRQ_NEST;    // lwz        r1,XLM_IRQ_NEST
  627.     *lp++ = 0x38210001;                    // addi        r1,r1,1
  628.     *lp++ = 0x90200000 + XLM_IRQ_NEST;    // stw        r1,XLM_IRQ_NEST
  629.     *lp++ = 0x80200000 + XLM_KERNEL_DATA;// lwz        r1,XLM_KERNEL_DATA
  630.     *lp++ = 0x90c10018;                    // stw        r6,0x18(r1)
  631.     *lp++ = 0x7cc902a6;                    // mfctr    r6
  632.     *lp++ = 0x90c10004;                    // stw        r6,$0004(r1)
  633.     *lp++ = 0x80c1065c;                    // lwz        r6,$065c(r1)
  634.     *lp++ = 0x90e6013c;                    // stw        r7,$013c(r6)
  635.     *lp++ = 0x91060144;                    // stw        r8,$0144(r6)
  636.     *lp++ = 0x9126014c;                    // stw        r9,$014c(r6)
  637.     *lp++ = 0x91460154;                    // stw        r10,$0154(r6)
  638.     *lp++ = 0x9166015c;                    // stw        r11,$015c(r6)
  639.     *lp++ = 0x91860164;                    // stw        r12,$0164(r6)
  640.     *lp++ = 0x91a6016c;                    // stw        r13,$016c(r6)
  641.     *lp++ = 0x7da00026;                    // mfcr        r13
  642.     *lp++ = 0x80e10660;                    // lwz        r7,$0660(r1)
  643.     *lp++ = 0x7d8802a6;                    // mflr        r12
  644.     *lp++ = 0x50e74001;                    // rlwimi.    r7,r7,8,$80000000
  645.     *lp++ = 0x814105f4;                    // lwz        r10,0x05f8(r1)
  646.     *lp++ = 0x7d4803a6;                    // mtlr        r10
  647.     *lp++ = 0x7d8a6378;                    // mr        r10,r12
  648.     *lp++ = 0x3d600002;                    // lis        r11,0x0002
  649.     *lp++ = 0x616bf072;                    // ori        r11,r11,0xf072 (MSR)
  650.     *lp++ = 0x50e7deb4;                    // rlwimi    r7,r7,27,$00000020
  651.     *lp++ = 0x4e800020;                    // blr
  652.  
  653.     // Patch DR emulator to jump to right address when an interrupt occurs
  654.     lp = (uint32 *)(ROM_BASE + 0x370000);
  655.     while (lp < (uint32 *)(ROM_BASE + 0x380000)) {
  656.         if (*lp == 0x4ca80020)        // bclr        5,8
  657.             goto dr_found;
  658.         lp++;
  659.     }
  660.     D(bug("DR emulator patch location not found\n"));
  661.     return false;
  662. dr_found:
  663.     lp++;
  664.     *lp = 0x48000000 + 0xf000 - ((uint32)lp & 0xffff);        // b    DR_CACHE_BASE+0x1f000
  665.     lp = (uint32 *)(ROM_BASE + 0x37f000);
  666.     *lp++ = 0x3c000000 + ((ROM_BASE + 0x46d0a4) >> 16);        // lis    r0,xxx
  667.     *lp++ = 0x60000000 + ((ROM_BASE + 0x46d0a4) & 0xffff);    // ori    r0,r0,xxx
  668.     *lp++ = 0x7c0903a6;                                        // mtctr    r0
  669.     *lp = POWERPC_BCTR;                                        // bctr
  670.     return true;
  671. }
  672.  
  673. // Nanokernel patches
  674. static bool patch_nanokernel(void)
  675. {
  676.     uint32 *lp;
  677.  
  678.     // Patch 68k emulator trap routine
  679.     lp = (uint32 *)(ROM_BASE + 0x312994);    // Always restore FPU state
  680.     while (*lp != 0x39260040) lp++;
  681.     lp--;
  682.     *lp = 0x48000441;                    // bl    0x00312dd4
  683.     lp = (uint32 *)(ROM_BASE + 0x312dd8);    // Don't modify MSR to turn on FPU
  684.     while (*lp != 0x810600e4) lp++;
  685.     lp--;
  686.     *lp++ = POWERPC_NOP;
  687.     lp += 2;
  688.     *lp++ = POWERPC_NOP;
  689.     lp++;
  690.     *lp++ = POWERPC_NOP;
  691.     *lp++ = POWERPC_NOP;
  692.     *lp = POWERPC_NOP;
  693.  
  694.     // Patch trap return routine
  695.     lp = (uint32 *)(ROM_BASE + 0x312c20);
  696.     while (*lp != 0x7d5a03a6) lp++;
  697.     *lp++ = 0x7d4903a6;                    // mtctr    r10
  698.     *lp++ = 0x7daff120;                    // mtcr    r13
  699.     *lp++ = 0x48000000 + 0x8000 - ((uint32)lp & 0xffff);    // b        ROM_BASE+0x318000
  700.     uint32 xlp = (uint32)lp & 0xffff;
  701.  
  702.     lp = (uint32 *)(ROM_BASE + 0x312c50);    // Replace rfi
  703.     while (*lp != 0x4c000064) lp++;
  704.     *lp = POWERPC_BCTR;
  705.  
  706.     lp = (uint32 *)(ROM_BASE + 0x318000);
  707.     *lp++ = 0x81400000 + XLM_IRQ_NEST;    // lwz    r10,XLM_IRQ_NEST
  708.     *lp++ = 0x394affff;                    // subi    r10,r10,1
  709.     *lp++ = 0x91400000 + XLM_IRQ_NEST;    // stw    r10,XLM_IRQ_NEST
  710.     *lp = 0x48000000 + ((xlp - 0x800c) & 0x03fffffc);    // b        ROM_BASE+0x312c2c
  711.     return true;
  712. }
  713.  
  714. static bool patch_rom(void)
  715. {
  716.     // Detect ROM type
  717.     if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot TNT", 8))
  718.         ROMType = ROMTYPE_TNT;
  719.     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Alchemy", 12))
  720.         ROMType = ROMTYPE_ALCHEMY;
  721.     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Zanzibar", 13))
  722.         ROMType = ROMTYPE_ZANZIBAR;
  723.     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gazelle", 12))
  724.         ROMType = ROMTYPE_GAZELLE;
  725.     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "NewWorld", 8))
  726.         ROMType = ROMTYPE_NEWWORLD;
  727.     else
  728.         return false;
  729.  
  730.     // Apply patches
  731.     if (!patch_nanokernel_boot()) return false;
  732.     if (!patch_68k_emul()) return false;
  733.     if (!patch_nanokernel()) return false;
  734.  
  735.     // Copy 68k emulator to 2MB boundary
  736.     memcpy((void *)(ROM_BASE + ROM_SIZE), (void *)(ROM_BASE + ROM_SIZE - 0x100000), 0x100000);
  737.     return true;
  738. }
  739.  
  740.  
  741. /*
  742.  *  Initialize 680x0 emulation
  743.  */
  744.  
  745. static asm void *get_toc(void)
  746. {
  747.     mr    r3,r2
  748.     blr
  749. }
  750.  
  751. bool Init680x0(void)
  752. {
  753.     char str[256];
  754.  
  755.     // Mac address space = host address space
  756.     RAMBaseMac = (uint32)RAMBaseHost;
  757.     ROMBaseMac = (uint32)ROMBaseHost;
  758.  
  759.     // Get TOC pointer
  760.     TOC = get_toc();
  761.  
  762.     // Get system info
  763.     get_system_info(&SysInfo);
  764.     switch (SysInfo.cpu_type) {
  765.         case B_CPU_PPC_601:
  766.             PVR = 0x00010000;
  767.             break;
  768.         case B_CPU_PPC_603:
  769.             PVR = 0x00030000;
  770.             break;
  771.         case B_CPU_PPC_603e:
  772.             PVR = 0x00060000;
  773.             break;
  774.         case B_CPU_PPC_604:
  775.             PVR = 0x00040000;
  776.             break;
  777.         case B_CPU_PPC_604e:
  778.             PVR = 0x00090000;
  779.             break;
  780.         default:
  781.             PVR = 0x00040000;
  782.             break;
  783.     }
  784.     CPUClockSpeed = SysInfo.cpu_clock_speed;
  785.     BusClockSpeed = SysInfo.bus_clock_speed;
  786.  
  787.     // Delete old areas
  788.     area_id old_kernel_area = find_area(KERNEL_AREA_NAME);
  789.     if (old_kernel_area > 0)
  790.         delete_area(old_kernel_area);
  791.     area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME);
  792.     if (old_dr_cache_area > 0)
  793.         delete_area(old_dr_cache_area);
  794.  
  795.     // Create area for Kernel Data
  796.     kernel_data = (KernelData *)0x68ffe000;
  797.     kernel_area = create_area(KERNEL_AREA_NAME, &kernel_data, B_EXACT_ADDRESS, 0x2000, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
  798.     if (kernel_area < 0) {
  799.         sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area), kernel_area);
  800.         ErrorAlert(str);
  801.         return false;
  802.     }
  803.     emulator_data = &kernel_data->ed;
  804.     KernelDataAddr = (uint32)kernel_data;
  805.     D(bug("Kernel Data area %ld at %p, Emulator Data at %p\n", kernel_area, kernel_data, emulator_data));
  806.  
  807.     // Load PowerMac ROM (upper 3MB)
  808.     try {
  809.         load_rom();
  810.     } catch (file_open_error) {
  811.         ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
  812.         return false;
  813.     } catch (file_read_error) {
  814.         ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
  815.         return false;
  816.     } catch (rom_size_error) {
  817.         ErrorAlert(GetString(STR_ROM_SIZE_ERR));
  818.         return false;
  819.     }
  820.  
  821.     // Install ROM patches
  822.     if (!patch_rom()) {
  823.         ErrorAlert("Unsupported PowerMac ROM version");
  824.         return false;
  825.     }
  826.  
  827.     // Create area for DR Cache
  828.     DRCacheAddr = DR_CACHE_BASE;
  829.     dr_cache_area = create_area(DR_CACHE_AREA_NAME, (void **)&DRCacheAddr, B_EXACT_ADDRESS, DR_CACHE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
  830.     if (dr_cache_area < 0) {
  831.         sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_cache_area), dr_cache_area);
  832.         ErrorAlert(str);
  833.         return false;
  834.     }
  835.     D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr));
  836.  
  837.     // Initialize Kernel Data
  838.     memset(kernel_data, 0, sizeof(KernelData));
  839.     if (ROMType == ROMTYPE_NEWWORLD) {
  840.         kernel_data->v[0xc20 >> 2] = RAMSize;
  841.         kernel_data->v[0xc24 >> 2] = RAMSize;
  842.         kernel_data->v[0xc30 >> 2] = RAMSize;
  843.         kernel_data->v[0xc34 >> 2] = RAMSize;
  844.         kernel_data->v[0xc38 >> 2] = 0x00010020;
  845.         kernel_data->v[0xc3c >> 2] = 0x00200001;
  846.         kernel_data->v[0xc40 >> 2] = 0x00010000;
  847.         kernel_data->v[0xc50 >> 2] = RAMBaseMac;
  848.         kernel_data->v[0xc54 >> 2] = RAMSize;
  849.         kernel_data->v[0xf60 >> 2] = PVR;
  850.         kernel_data->v[0xf64 >> 2] = CPUClockSpeed;
  851.         kernel_data->v[0xf68 >> 2] = BusClockSpeed;
  852.         kernel_data->v[0xf6c >> 2] = CPUClockSpeed;
  853.     } else {
  854.         kernel_data->v[0xc80 >> 2] = RAMSize;
  855.         kernel_data->v[0xc84 >> 2] = RAMSize;
  856.         kernel_data->v[0xc90 >> 2] = RAMSize;
  857.         kernel_data->v[0xc94 >> 2] = RAMSize;
  858.         kernel_data->v[0xc98 >> 2] = 0x00010020;
  859.         kernel_data->v[0xc9c >> 2] = 0x00200001;
  860.         kernel_data->v[0xca0 >> 2] = 0x00010000;
  861.         kernel_data->v[0xcb0 >> 2] = RAMBaseMac;
  862.         kernel_data->v[0xcb4 >> 2] = RAMSize;
  863.         kernel_data->v[0xf80 >> 2] = PVR;
  864.         kernel_data->v[0xf84 >> 2] = CPUClockSpeed;
  865.         kernel_data->v[0xf88 >> 2] = BusClockSpeed;
  866.         kernel_data->v[0xf8c >> 2] = CPUClockSpeed;
  867.     }
  868.  
  869.     // Initialize extra low memory
  870.     memset((void *)0x2000, 0, 0x1000);
  871.     *(uint32 *)XLM_RESET_STACK = 0x2000;        // Reset stack pointer
  872.     *(KernelData **)XLM_KERNEL_DATA = kernel_data;// For trap replacement routines
  873.     *(void **)XLM_TOC = TOC;                    // TOC pointer of emulator
  874.     *(uint32 *)XLM_PVR = PVR;                    // Theoretical PVR
  875.  
  876.     // Clear caches (as we loaded and patched code)
  877.     clear_caches((void *)ROM_BASE, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE);
  878.     return true;
  879. }
  880.  
  881.  
  882. /*
  883.  *  Deinitialize 680x0 emulation
  884.  */
  885.  
  886. void Exit680x0(void)
  887. {
  888.     // Delete DR Cache area
  889.     if (dr_cache_area >= 0)
  890.         delete_area(dr_cache_area);
  891.  
  892.     // Delete Kernel Data area
  893.     if (kernel_area >= 0)
  894.         delete_area(kernel_area);
  895. }
  896.  
  897.  
  898. /*
  899.  *  Quit emulator (must only be called from main thread)
  900.  */
  901.  
  902. asm void QuitEmulator(void)
  903. {
  904.     lwz        r0,XLM_EMUL_RETURN_PROC
  905.     mtlr    r0
  906.     blr
  907. }
  908.  
  909.  
  910. /*
  911.  *  Reset and start 680x0 emulation
  912.  */
  913.  
  914. static asm void jump_to_rom(register uint32 entry)
  915. {
  916.     // Create stack frame
  917.     mflr    r0
  918.     stw        r0,8(r1)
  919.     mfcr    r0
  920.     stw        r0,4(r1)
  921.     stwu    r1,-(56+19*4+18*8)(r1)
  922.  
  923.     // Save PowerPC registers
  924.     stmw    r13,56(r1)
  925.     stfd    f14,56+19*4+0*8(r1)
  926.     stfd    f15,56+19*4+1*8(r1)
  927.     stfd    f16,56+19*4+2*8(r1)
  928.     stfd    f17,56+19*4+3*8(r1)
  929.     stfd    f18,56+19*4+4*8(r1)
  930.     stfd    f19,56+19*4+5*8(r1)
  931.     stfd    f20,56+19*4+6*8(r1)
  932.     stfd    f21,56+19*4+7*8(r1)
  933.     stfd    f22,56+19*4+8*8(r1)
  934.     stfd    f23,56+19*4+9*8(r1)
  935.     stfd    f24,56+19*4+10*8(r1)
  936.     stfd    f25,56+19*4+11*8(r1)
  937.     stfd    f26,56+19*4+12*8(r1)
  938.     stfd    f27,56+19*4+13*8(r1)
  939.     stfd    f28,56+19*4+14*8(r1)
  940.     stfd    f29,56+19*4+15*8(r1)
  941.     stfd    f30,56+19*4+16*8(r1)
  942.     stfd    f31,56+19*4+17*8(r1)
  943.  
  944.     // Move entry address to ctr, get pointer to Emulator Data
  945.     mtctr    r3
  946.     lwz        r3,emulator_data(r2)
  947.  
  948.     // Skip over EMUL_RETURN routine and get its address
  949.     bl        @1
  950.  
  951.  
  952.     /*
  953.      *  EMUL_RETURN: Returned from emulator
  954.      */
  955.  
  956.     // Restore PowerPC registers
  957.     lwz        r1,XLM_EMUL_RETURN_STACK
  958.     lwz        r2,XLM_TOC
  959.     lmw        r13,56(r1)
  960.     lfd        f14,56+19*4+0*8(r1)
  961.     lfd        f15,56+19*4+1*8(r1)
  962.     lfd        f16,56+19*4+2*8(r1)
  963.     lfd        f17,56+19*4+3*8(r1)
  964.     lfd        f18,56+19*4+4*8(r1)
  965.     lfd        f19,56+19*4+5*8(r1)
  966.     lfd        f20,56+19*4+6*8(r1)
  967.     lfd        f21,56+19*4+7*8(r1)
  968.     lfd        f22,56+19*4+8*8(r1)
  969.     lfd        f23,56+19*4+9*8(r1)
  970.     lfd        f24,56+19*4+10*8(r1)
  971.     lfd        f25,56+19*4+11*8(r1)
  972.     lfd        f26,56+19*4+12*8(r1)
  973.     lfd        f27,56+19*4+13*8(r1)
  974.     lfd        f28,56+19*4+14*8(r1)
  975.     lfd        f29,56+19*4+15*8(r1)
  976.     lfd        f30,56+19*4+16*8(r1)
  977.     lfd        f31,56+19*4+17*8(r1)
  978.  
  979.     // Exiting from 68k emulator
  980.     li        r0,1
  981.     stw        r0,XLM_IRQ_NEST
  982.     li        r0,MODE_EMUL_OP
  983.     stw        r0,XLM_RUN_MODE
  984.  
  985.     // Return to caller of jump_to_rom()
  986.     lwz        r0,56+19*4+18*8+8(r1)
  987.     mtlr    r0
  988.     lwz        r0,56+19*4+18*8+4(r1)
  989.     mtcrf    0xff,r0
  990.     addi    r1,r1,56+19*4+18*8
  991.     blr
  992.  
  993.  
  994.     // Save address of EMUL_RETURN routine for 68k emulator patch
  995. @1    mflr    r0
  996.     stw        r0,XLM_EMUL_RETURN_PROC
  997.  
  998.     // Skip over EXEC_RETURN routine and get its address
  999.     bl        @2
  1000.  
  1001.  
  1002.     /*
  1003.      *  EXEC_RETURN: Returned from 68k routine executed with Execute68k()
  1004.      */
  1005.  
  1006.     // Save r25 (contains current 68k interrupt level)
  1007.     stw        r25,XLM_68K_R25
  1008.  
  1009.     // Reentering EMUL_OP mode
  1010.     li        r0,MODE_EMUL_OP
  1011.     stw        r0,XLM_RUN_MODE
  1012.  
  1013.     // Save 68k registers
  1014.     lwz        r4,56+19*4+18*8+12(r1)
  1015.     stw        r8,M68kRegisters.d[0](r4)
  1016.     stw        r9,M68kRegisters.d[1](r4)
  1017.     stw        r10,M68kRegisters.d[2](r4)
  1018.     stw        r11,M68kRegisters.d[3](r4)
  1019.     stw        r12,M68kRegisters.d[4](r4)
  1020.     stw        r13,M68kRegisters.d[5](r4)
  1021.     stw        r14,M68kRegisters.d[6](r4)
  1022.     stw        r15,M68kRegisters.d[7](r4)
  1023.     stw        r16,M68kRegisters.a[0](r4)
  1024.     stw        r17,M68kRegisters.a[1](r4)
  1025.     stw        r18,M68kRegisters.a[2](r4)
  1026.     stw        r19,M68kRegisters.a[3](r4)
  1027.     stw        r20,M68kRegisters.a[4](r4)
  1028.     stw        r21,M68kRegisters.a[5](r4)
  1029.     stw        r22,M68kRegisters.a[6](r4)
  1030.  
  1031.     // Restore PowerPC registers
  1032.     lmw        r13,56(r1)
  1033. #if SAVE_FP_EXEC_68K
  1034.     lfd        f14,56+19*4+0*8(r1)
  1035.     lfd        f15,56+19*4+1*8(r1)
  1036.     lfd        f16,56+19*4+2*8(r1)
  1037.     lfd        f17,56+19*4+3*8(r1)
  1038.     lfd        f18,56+19*4+4*8(r1)
  1039.     lfd        f19,56+19*4+5*8(r1)
  1040.     lfd        f20,56+19*4+6*8(r1)
  1041.     lfd        f21,56+19*4+7*8(r1)
  1042.     lfd        f22,56+19*4+8*8(r1)
  1043.     lfd        f23,56+19*4+9*8(r1)
  1044.     lfd        f24,56+19*4+10*8(r1)
  1045.     lfd        f25,56+19*4+11*8(r1)
  1046.     lfd        f26,56+19*4+12*8(r1)
  1047.     lfd        f27,56+19*4+13*8(r1)
  1048.     lfd        f28,56+19*4+14*8(r1)
  1049.     lfd        f29,56+19*4+15*8(r1)
  1050.     lfd        f30,56+19*4+16*8(r1)
  1051.     lfd        f31,56+19*4+17*8(r1)
  1052. #endif
  1053.  
  1054.     // Return to caller
  1055.     lwz        r0,56+19*4+18*8+8(r1)
  1056.     mtlr    r0
  1057.     addi    r1,r1,56+19*4+18*8
  1058.     blr
  1059.  
  1060.  
  1061.     // Stave address of EXEC_RETURN routine for 68k emulator patch
  1062. @2    mflr    r0
  1063.     stw        r0,XLM_EXEC_RETURN_PROC
  1064.  
  1065.     // Skip over EMUL_OP routine and get its address
  1066.     bl        @3
  1067.  
  1068.  
  1069.     /*
  1070.      *  EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
  1071.      *
  1072.      *  68k registers are stored in a M68kRegisters struct on the stack
  1073.      *  which the native routine may read and modify
  1074.      */
  1075.  
  1076.     // Save r25 (contains current 68k interrupt level)
  1077.     stw        r25,XLM_68K_R25
  1078.  
  1079.     // Entering EMUL_OP mode within 68k emulator
  1080.     li        r0,MODE_EMUL_OP
  1081.     stw        r0,XLM_RUN_MODE
  1082.  
  1083.     // Create PowerPC stack frame, reserve space for M68kRegisters
  1084.     mr        r3,r1
  1085.     subi    r1,r1,56        // Fake "caller" frame
  1086.     rlwinm    r1,r1,0,0,29    // Align stack
  1087.  
  1088.     mfcr    r0
  1089.     rlwinm    r0,r0,0,11,8
  1090.     stw        r0,4(r1)
  1091.     mfxer    r0
  1092.     stw        r0,16(r1)
  1093.     stw        r2,12(r1)
  1094.     stwu    r1,-(56+16*4+15*8)(r1)
  1095.     lwz        r2,XLM_TOC
  1096.  
  1097.     // Save 68k registers
  1098.     stw        r8,56+M68kRegisters.d[0](r1)
  1099.     stw        r9,56+M68kRegisters.d[1](r1)
  1100.     stw        r10,56+M68kRegisters.d[2](r1)
  1101.     stw        r11,56+M68kRegisters.d[3](r1)
  1102.     stw        r12,56+M68kRegisters.d[4](r1)
  1103.     stw        r13,56+M68kRegisters.d[5](r1)
  1104.     stw        r14,56+M68kRegisters.d[6](r1)
  1105.     stw        r15,56+M68kRegisters.d[7](r1)
  1106.     stw        r16,56+M68kRegisters.a[0](r1)
  1107.     stw        r17,56+M68kRegisters.a[1](r1)
  1108.     stw        r18,56+M68kRegisters.a[2](r1)
  1109.     stw        r19,56+M68kRegisters.a[3](r1)
  1110.     stw        r20,56+M68kRegisters.a[4](r1)
  1111.     stw        r21,56+M68kRegisters.a[5](r1)
  1112.     stw        r22,56+M68kRegisters.a[6](r1)
  1113.     stw        r3,56+M68kRegisters.a[7](r1)
  1114.     stfd    f0,56+16*4+0*8(r1)
  1115.     stfd    f1,56+16*4+1*8(r1)
  1116.     stfd    f2,56+16*4+2*8(r1)
  1117.     stfd    f3,56+16*4+3*8(r1)
  1118.     stfd    f4,56+16*4+4*8(r1)
  1119.     stfd    f5,56+16*4+5*8(r1)
  1120.     stfd    f6,56+16*4+6*8(r1)
  1121.     stfd    f7,56+16*4+7*8(r1)
  1122.     mffs    f0
  1123.     stfd    f8,56+16*4+8*8(r1)
  1124.     stfd    f9,56+16*4+9*8(r1)
  1125.     stfd    f10,56+16*4+10*8(r1)
  1126.     stfd    f11,56+16*4+11*8(r1)
  1127.     stfd    f12,56+16*4+12*8(r1)
  1128.     stfd    f13,56+16*4+13*8(r1)
  1129.     stfd    f0,56+16*4+14*8(r1)
  1130.  
  1131.     // Execute native routine
  1132.     mr        r3,r5
  1133.     addi    r4,r1,56
  1134.     bl        EmulOp
  1135.  
  1136.     // Restore 68k registers
  1137.     lwz        r8,56+M68kRegisters.d[0](r1)
  1138.     lwz        r9,56+M68kRegisters.d[1](r1)
  1139.     lwz        r10,56+M68kRegisters.d[2](r1)
  1140.     lwz        r11,56+M68kRegisters.d[3](r1)
  1141.     lwz        r12,56+M68kRegisters.d[4](r1)
  1142.     lwz        r13,56+M68kRegisters.d[5](r1)
  1143.     lwz        r14,56+M68kRegisters.d[6](r1)
  1144.     lwz        r15,56+M68kRegisters.d[7](r1)
  1145.     lwz        r16,56+M68kRegisters.a[0](r1)
  1146.     lwz        r17,56+M68kRegisters.a[1](r1)
  1147.     lwz        r18,56+M68kRegisters.a[2](r1)
  1148.     lwz        r19,56+M68kRegisters.a[3](r1)
  1149.     lwz        r20,56+M68kRegisters.a[4](r1)
  1150.     lwz        r21,56+M68kRegisters.a[5](r1)
  1151.     lwz        r22,56+M68kRegisters.a[6](r1)
  1152.     lwz        r3,56+M68kRegisters.a[7](r1)
  1153.     lfd        f13,56+16*4+14*8(r1)
  1154.     lfd        f0,56+16*4+0*8(r1)
  1155.     lfd        f1,56+16*4+1*8(r1)
  1156.     lfd        f2,56+16*4+2*8(r1)
  1157.     lfd        f3,56+16*4+3*8(r1)
  1158.     lfd        f4,56+16*4+4*8(r1)
  1159.     lfd        f5,56+16*4+5*8(r1)
  1160.     lfd        f6,56+16*4+6*8(r1)
  1161.     lfd        f7,56+16*4+7*8(r1)
  1162.     mtfsf    0xff,f13
  1163.     lfd        f8,56+16*4+8*8(r1)
  1164.     lfd        f9,56+16*4+9*8(r1)
  1165.     lfd        f10,56+16*4+10*8(r1)
  1166.     lfd        f11,56+16*4+11*8(r1)
  1167.     lfd        f12,56+16*4+12*8(r1)
  1168.     lfd        f13,56+16*4+13*8(r1)
  1169.  
  1170.     // Delete PowerPC stack frame
  1171.     lwz        r2,56+16*4+15*8+12(r1)
  1172.     lwz        r0,56+16*4+15*8+16(r1)
  1173.     mtxer    r0
  1174.     lwz        r0,56+16*4+15*8+4(r1)
  1175.     mtcrf    0xff,r0
  1176.     mr        r1,r3
  1177.  
  1178.     // Reeintering 68k emulator
  1179.     li        r0,MODE_68K
  1180.     stw        r0,XLM_RUN_MODE
  1181.  
  1182.     // Set r0 to 0 for 68k emulator
  1183.     li        r0,0
  1184.  
  1185.     // Execute next 68k opcode
  1186.     rlwimi    r29,r27,3,13,28
  1187.     lhau    r27,2(r24)
  1188.     mtlr    r29
  1189.     blr
  1190.  
  1191.  
  1192.     // Save address of EMUL_OP routine for 68k emulator patch
  1193. @3    mflr    r0
  1194.     stw        r0,XLM_EMUL_OP_PROC
  1195.  
  1196.     // Save stack pointer for EMUL_RETURN
  1197.     stw        r1,XLM_EMUL_RETURN_STACK
  1198.  
  1199.     // Preset registers for ROM boot routine
  1200.     lis        r3,0x40b0        // Pointer to ROM boot structure
  1201.     ori        r3,r3,0xd000
  1202.  
  1203.     // 68k emulator is now active
  1204.     li        r0,MODE_68K
  1205.     stw        r0,XLM_RUN_MODE
  1206.  
  1207.     // Jump to ROM
  1208.     bctr
  1209. }
  1210.  
  1211. void Start680x0(void)
  1212. {
  1213.     // Install interrupt signal handler
  1214.     sigemptyset(&sigusr1_action.sa_mask);
  1215.     sigusr1_action.sa_handler = (__signal_func_ptr)(sigusr1_handler);
  1216.     sigusr1_action.sa_flags = 0;
  1217.     sigusr1_action.sa_userdata = NULL;
  1218.     sigaction(SIGUSR1, &sigusr1_action, NULL);
  1219.  
  1220.     // Install signal stack
  1221.     set_signal_stack(malloc(SIG_STACK_SIZE), SIG_STACK_SIZE);
  1222.  
  1223.     // We're now ready to receive signals
  1224.     ReadyForSignals = true;
  1225.  
  1226.     D(bug("Jumping to ROM\n"));
  1227.     jump_to_rom(ROM_BASE + 0x310000);
  1228.     D(bug("Returned from ROM\n"));
  1229.  
  1230.     // We're no longer ready to receive signals
  1231.     ReadyForSignals = false;
  1232. }
  1233.  
  1234.  
  1235. /*
  1236.  *  Trigger interrupt
  1237.  */
  1238.  
  1239. void TriggerInterrupt(void)
  1240. {
  1241.     if (emul_thread > 0 && ReadyForSignals)
  1242.         send_signal(emul_thread, SIGUSR1);
  1243. }
  1244.  
  1245. void TriggerNMI(void)
  1246. {
  1247.     //!! not implemented yet
  1248. }
  1249.  
  1250.  
  1251. /*
  1252.  *  Execute 68k subroutine
  1253.  *  r->a[7] and r->sr are unused!
  1254.  */
  1255.  
  1256. static asm void execute_68k(register uint32 addr, register M68kRegisters *r)
  1257. {
  1258.     // Create stack frame
  1259.     mflr    r0
  1260.     stw        r0,8(r1)
  1261.     stw        r4,12(r1)
  1262.     stwu    r1,-(56+19*4+18*8)(r1)
  1263.  
  1264.     // Save PowerPC registers
  1265.     stmw    r13,56(r1)
  1266. #if SAVE_FP_EXEC_68K
  1267.     stfd    f14,56+19*4+0*8(r1)
  1268.     stfd    f15,56+19*4+1*8(r1)
  1269.     stfd    f16,56+19*4+2*8(r1)
  1270.     stfd    f17,56+19*4+3*8(r1)
  1271.     stfd    f18,56+19*4+4*8(r1)
  1272.     stfd    f19,56+19*4+5*8(r1)
  1273.     stfd    f20,56+19*4+6*8(r1)
  1274.     stfd    f21,56+19*4+7*8(r1)
  1275.     stfd    f22,56+19*4+8*8(r1)
  1276.     stfd    f23,56+19*4+9*8(r1)
  1277.     stfd    f24,56+19*4+10*8(r1)
  1278.     stfd    f25,56+19*4+11*8(r1)
  1279.     stfd    f26,56+19*4+12*8(r1)
  1280.     stfd    f27,56+19*4+13*8(r1)
  1281.     stfd    f28,56+19*4+14*8(r1)
  1282.     stfd    f29,56+19*4+15*8(r1)
  1283.     stfd    f30,56+19*4+16*8(r1)
  1284.     stfd    f31,56+19*4+17*8(r1)
  1285. #endif
  1286.  
  1287.     // Set up registers for 68k emulator
  1288.     lwz        r31,XLM_KERNEL_DATA    // Pointer to Kernel Data
  1289.     addi    r31,r31,0x1000        // points to Emulator Data
  1290.     li        r0,0
  1291.     mtcrf    0xff,r0
  1292.     creqv    11,11,11            // Supervisor mode
  1293.     lwz        r8,M68kRegisters.d[0](r4)
  1294.     lwz        r9,M68kRegisters.d[1](r4)
  1295.     lwz        r10,M68kRegisters.d[2](r4)
  1296.     lwz        r11,M68kRegisters.d[3](r4)
  1297.     lwz        r12,M68kRegisters.d[4](r4)
  1298.     lwz        r13,M68kRegisters.d[5](r4)
  1299.     lwz        r14,M68kRegisters.d[6](r4)
  1300.     lwz        r15,M68kRegisters.d[7](r4)
  1301.     lwz        r16,M68kRegisters.a[0](r4)
  1302.     lwz        r17,M68kRegisters.a[1](r4)
  1303.     lwz        r18,M68kRegisters.a[2](r4)
  1304.     lwz        r19,M68kRegisters.a[3](r4)
  1305.     lwz        r20,M68kRegisters.a[4](r4)
  1306.     lwz        r21,M68kRegisters.a[5](r4)
  1307.     lwz        r22,M68kRegisters.a[6](r4)
  1308.     li        r23,0
  1309.     mr        r24,r3
  1310.     lwz        r25,XLM_68K_R25        // MSB of SR
  1311.     li        r26,0
  1312.     li        r28,0                // VBR
  1313.     lwz        r29,0x74(r31)        // Pointer to opcode table
  1314.     lwz        r30,0x78(r31)        // Address of emulator
  1315.  
  1316.     // Reentering 68k emulator
  1317.     li        r0,MODE_68K
  1318.     stw        r0,XLM_RUN_MODE
  1319.  
  1320.     // Set r0 to 0 for 68k emulator
  1321.     li        r0,0
  1322.  
  1323.     // Execute 68k opcode
  1324.     lha        r27,0(r24)
  1325.     rlwimi    r29,r27,3,13,28
  1326.     lhau    r27,2(r24)
  1327.     mtlr    r29
  1328.     blr
  1329. }
  1330.  
  1331. void Execute68k(uint32 addr, M68kRegisters *r)
  1332. {
  1333.     uint16 proc[4] = {M68K_JSR, addr >> 16, addr & 0xffff, M68K_EXEC_RETURN};
  1334.     execute_68k((uint32)proc, r);
  1335. }
  1336.  
  1337.  
  1338. /*
  1339.  *  Execute MacOS 68k trap
  1340.  *  r->a[7] and r->sr are unused!
  1341.  */
  1342.  
  1343. void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
  1344. {
  1345.     uint16 proc[2] = {trap, M68K_EXEC_RETURN};
  1346.     execute_68k((uint32)proc, r);
  1347. }
  1348.  
  1349.  
  1350. /*
  1351.  *  USR1 handler
  1352.  */
  1353.  
  1354. static void sigusr1_handler(int sig, void *arg, vregs *r)
  1355. {
  1356.     // Do nothing if interrupts are disabled
  1357.     if ((*(int32 *)XLM_IRQ_NEST) > 0)
  1358.         return;
  1359.  
  1360.     // 68k emulator active? Then trigger 68k interrupt level 1
  1361.     if (*(uint32 *)XLM_RUN_MODE == MODE_68K) {
  1362.         *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1;
  1363.         r->cr |= kernel_data->v[0x674 >> 2];
  1364.     }
  1365. }
  1366.